import React, { useEffect, useCallback, useMemo, lazy, Suspense } from 'react';
import { connect } from 'react-redux';
import './App.css';
import URI from 'urijs';
import { h0 } from '../common/fp';
import dayjs from 'dayjs';

import Header from '../common/Header';
import Nav from '../common/Nav';
import useNav from '../common/useNav';
import Detail from '../common/Detail';
import Candidate from './Candidate';
// import Schedule from './Schedule'

import { TrainContext } from './context';

import {
  setDepartStation,
  setArriveStation,
  setTrainNumber,
  setDepartDate,
  setSearchParsed,
  prevDay,
  nextDay,
  setDepartTimeStr,
  setArriveTimeStr,
  setArriveDate,
  setDurationStr,
  setTickets,
  toggleIsSchedualVisible,
} from './actions';
import { bindActionCreators } from 'redux';

// 异步组件
const Schedule = lazy(() => import('./Schedule'));
function App(props) {
  const {
    //出发日期
    departDate,
    //到达日期
    arriveDate,
    //出发时间  从服务端获取数据
    departTimeStr,
    //到达时间
    arriveTimeStr,
    //出发车站
    departStation,
    //到达车站
    arriveStation,
    //车次
    trainNumber,
    //运行时间
    durationStr,
    //座次和售票道
    tickets,
    //小浮层弹出
    isSchedualVisible,
    //解析location的url参数
    searchParsed,

    dispatch,
  } = props;

  const onBack = useCallback(() => {
    window.history.back();
  }, []);

  useEffect(() => {
    const queries = URI.parseQuery(window.location.search);
    const { aStation, dStation, date, trainNumber } = queries;
    dispatch(setDepartStation(dStation));
    dispatch(setArriveStation(aStation));
    dispatch(setTrainNumber(trainNumber));
    // 字符串转为时间戳毫秒值
    dispatch(setDepartDate(h0(dayjs(date).valueOf())));
    dispatch(setSearchParsed(true));
  }, [dispatch]);

  useEffect(() => {
    if (!searchParsed) {
      return;
    }

    //发起异步请求
    const url = new URI('/rest/ticket')
      .setSearch('date', dayjs(departDate).format('YYYY-MM-DD'))
      .setSearch('trainNumber', trainNumber)
      .toString();
    fetch(url)
      .then((res) => res.json())
      .then((result) => {
        const {
          detail: { departTimeStr, arriveTimeStr, arriveDate, durationStr },
          candidates,
        } = result;
        dispatch(setDepartTimeStr(departTimeStr));
        dispatch(setArriveTimeStr(arriveTimeStr));
        dispatch(setArriveDate(arriveDate));
        dispatch(setDurationStr(durationStr));
        dispatch(setTickets(candidates));
      });
  }, [departDate, dispatch, searchParsed, trainNumber]);
  useEffect(() => {
    document.title = trainNumber;
  }, [trainNumber]);
  const { isPrevDisable, isNextDisable, prev, next } = useNav(
    departDate,
    dispatch,
    prevDay,
    nextDay
  );

  const detailCbs = useMemo(() => {
    return bindActionCreators({ toggleIsSchedualVisible }, dispatch);
  }, [dispatch]);
  if (!searchParsed) {
    return null;
  }

  return (
    <div className="app">
      {/* 标题栏 */}
      <div className="header-wrapper">
        <Header title={trainNumber} onBack={onBack} />
      </div>
      {/* 日期选择 */}
      <div className="nav-wrapper">
        <Nav
          date={departDate}
          prev={prev}
          next={next}
          isPrevDisabled={isPrevDisable}
          isNextDisabled={isNextDisable}
        />
      </div>
      {/* 详情信息 */}
      <div className="detail-wrapper">
        <Detail
          departDate={departDate}
          arriveDate={arriveDate}
          departTimeStr={departTimeStr}
          arriveTimeStr={arriveTimeStr}
          trainNumber={trainNumber}
          departStation={departStation}
          arriveStation={arriveStation}
          durationStr={durationStr}
        >
          <span className="left"></span>
          <span
            className="middle"
            onClick={() => detailCbs.toggleIsSchedualVisible()}
          >
            时刻表
          </span>
          <span className="right"></span>
        </Detail>
      </div>
      <TrainContext.Provider
        value={{
          departDate,
          trainNumber,
          departStation,
          arriveStation,
        }}
      >
        <Candidate tickets={tickets} />
      </TrainContext.Provider>
      {/* 浮层 */}
      {isSchedualVisible && (
        <div
          className="mask"
          onClick={() => dispatch(toggleIsSchedualVisible())}
        >
          <Suspense fallback={<div>loading</div>}>
            <Schedule
              date={departDate}
              trainNumber={trainNumber}
              departStation={departStation}
              arriveStation={arriveStation}
            />
          </Suspense>
        </div>
      )}
    </div>
  );
}

const mapStateToProps = (state) => {
  return state;
};

const mapDispatchToProps = (dispatch) => {
  return { dispatch };
};
export default connect(mapStateToProps, mapDispatchToProps)(App);
